/*****************************************************************************
* Project:
* All project
* Copyright(C) 2020-2021 Shenju Co.Ltd, All rights reserved.
* Description:
* All code is genrated by yangyang
* Author:
* yangyang
****************************************************************************/
#include "oal_type.h"
#include "oal_thread.h"
#include "oal_queue.h"
#include "oal_mem.h"

#include <memory.h>

typedef struct {
	unsigned short				msg_num;
	unsigned short				msg_max_count;
	unsigned short				msg_get_index;
	unsigned short				msg_post_index;
	OAL_SEM						msg_get_sem;
	OAL_SEM						msg_post_sem;
	void*						msg_buff;
	int							msg_size;
	OAL_MUTEX					get_lock;
	OAL_MUTEX					post_lock;
}MY_MESSAGE;

int OAL_queue_create(OAL_QUEUE* qhandle, const char* name, int msgsize, OAL_QUEUE_POOL* poolname)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)OAL_calloc(1, sizeof(MY_MESSAGE));
	if (ret)
	{
		ret->msg_max_count = (unsigned short)(poolname->size / msgsize);
		ret->msg_buff = OAL_calloc(ret->msg_max_count, msgsize);
		if (ret)
		{
			ret->msg_get_sem = OAL_sem_create_count(0, ret->msg_max_count);
			ret->msg_post_sem = OAL_sem_create_count(ret->msg_max_count, ret->msg_max_count);
			ret->get_lock = OAL_mutex_create();
			ret->post_lock = OAL_mutex_create();
			ret->msg_size = msgsize;
			*qhandle = ret;
			return OAL_SUCCESS;
		}
		else
		{
			OAL_free(ret);
			return OAL_FAILED;
		}
	}

	return OAL_FAILED;
}


int OAL_queue_send(OAL_QUEUE* qhandle, const void* msg, unsigned long wait)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)*qhandle;

	if (!qhandle || !(*qhandle))
		return OAL_FAILED;

	if (OAL_SUCCESS == OAL_sem_wait_timeout(&ret->msg_post_sem, wait))
	{
		unsigned short newindex;

		OAL_mutex_lock(&ret->post_lock);

		newindex = ret->msg_post_index;

		memcpy((char *)ret->msg_buff + newindex*(unsigned short)ret->msg_size, msg, ret->msg_size);

		ret->msg_post_index++;
		ret->msg_post_index %= ret->msg_max_count;
		ret->msg_num++;

		OAL_sem_post(&ret->msg_get_sem);
		OAL_mutex_unlock(&ret->post_lock);
		return OAL_SUCCESS;
	}
		
	return OAL_FAILED;
}

int OAL_queue_recv(OAL_QUEUE* qhandle, void* msg, unsigned long wait)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)*qhandle;
	if (!qhandle || !(*qhandle))
		return OAL_FAILED;

	if (OAL_SUCCESS == OAL_sem_wait_timeout(&ret->msg_get_sem, wait))
	{
		OAL_mutex_lock(&ret->get_lock);

		memcpy((char *)msg, (char *)ret->msg_buff + ret->msg_get_index*ret->msg_size, ret->msg_size);

		ret->msg_get_index++;
		ret->msg_get_index %= ret->msg_max_count;
		ret->msg_num--;

		OAL_sem_post(&ret->msg_post_sem);
		OAL_mutex_unlock(&ret->get_lock);
		return OAL_SUCCESS;
	}

	return OAL_FAILED;
}

int OAL_queue_delete(OAL_QUEUE* qhandle)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)*qhandle;
	if (!qhandle || !(*qhandle))
		return OAL_FAILED;

	OAL_sem_destroy(&ret->msg_get_sem);
	OAL_sem_destroy(&ret->msg_post_sem);
	OAL_mutex_destroy(&ret->get_lock);
	OAL_mutex_destroy(&ret->post_lock);

	OAL_free(ret->msg_buff);
	OAL_free(ret);

	return OAL_SUCCESS;
}

int OAL_queue_get_msgs_waiting(OAL_QUEUE* qhandle)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)*qhandle;
	int nmsg = 0;
	if (!qhandle || !(*qhandle))
		return OAL_FAILED;
	nmsg = ret->msg_num;
	return nmsg;
}

int OAL_queue_reset(OAL_QUEUE* qhandle)
{
	MY_MESSAGE *ret = (MY_MESSAGE *)*qhandle;
	if (!qhandle || !(*qhandle))
		return OAL_FAILED;

	if (OAL_SUCCESS == OAL_sem_wait_timeout(&ret->msg_get_sem, 0))
	{
		OAL_mutex_lock(&ret->get_lock);

		ret->msg_get_index++;
		ret->msg_get_index %= ret->msg_max_count;
		ret->msg_num--;

		OAL_sem_post(&ret->msg_post_sem);
		OAL_mutex_unlock(&ret->get_lock);
	}

	return OAL_SUCCESS;
}